import {
  BadRequestException,
  ForbiddenException,
  Injectable,
} from '@nestjs/common';
import { CreateDepartmentDto } from './dto/create-department.dto';
import { UpdateDepartmentDto } from './dto/update-department.dto';
import { PrismaService } from 'nestjs-prisma';
import { BaseService } from '../../common/crud/base.service';
import { DepartmentEntity } from './entities/department.entity';
import { QueryDepartmentDto } from './dto/query-department.dto';

@Injectable()
export class DepartmentService extends BaseService {
  constructor(prisma: PrismaService) {
    super(prisma, 'department');
  }

  async update(id: string, form: UpdateDepartmentDto) {
    const dep = await this.prisma.department.findUniqueOrThrow({
      where: { id },
    });

    if (dep.id === form.parentId) {
      throw new ForbiddenException('部门不能设置为自己的父部门！');
    }

    if (form.parentId) {
      // 递归查询自己所有下级部门
      const descendants = await this.getAllDescendants(id);
      if (descendants.includes(form.parentId)) {
        throw new ForbiddenException('不能移动到自己的子部门下');
      }
    }

    return super.update(id, form);
  }

  // 递归获取所有子部门
  async getAllDescendants(id: string): Promise<string[]> {
    const children = await this.prisma.department.findMany({
      where: { parentId: id },
      select: { id: true },
    });

    const ids = children.map((c) => c.id);
    for (const child of children) {
      ids.push(...(await this.getAllDescendants(child.id)));
    }
    return ids;
  }

  findAll(query: QueryDepartmentDto) {
    return this.prisma.department.findMany({
      where: {
        name: {
          contains: query.name,
          mode: 'insensitive',
        },
      },
      select: {
        id: true,
        name: true,
        leader: true,
        parentId: true,
        remark: true,
        weight: true,
        createdAt: true,
        updatedAt: true,
        _count: {
          select: {
            employees: true,
          },
        },
      },
    });
  }

  async remove(id: string) {
    const dep = await this.prisma.department.findUniqueOrThrow({
      where: { id },
      select: {
        id: true,
        _count: {
          select: {
            employees: true,
            children: true,
          },
        },
      },
    });

    if (dep._count.employees > 0) {
      throw new ForbiddenException('部门下有员工，不允许删除！');
    }

    if (dep._count.children > 0) {
      throw new ForbiddenException('部门下有子部门，不允许删除！');
    }

    return super.remove(id);
  }
}
